require 'ostruct'
include ApplicationHelper
include WishListsHelper
include CatalogsHelper

class CatalogsController < ApplicationController
  prepend_before_filter :authenticate_user!, :except => [:index, :sort_catalog, :special_return_to, :advanced_search_view, :advanced_search, :free_text_search, :show_material_details, :find, :find_all_thematics, :find_all_authors,:find_all_countries, :find_all_publishers, :find_all_years, :find_all_editions, :load_trees_filters, :paginate_materials, :paginate_tree_thematics_filter, :paginate_tree_authors, :paginate_tree_countries, :paginate_tree_editors, :paginate_tree_years, :paginate_tree_editions, :index_without_clean, :find_only_param, :auto_complete_descriptor, :go_to_filters, :return_from_material_details]
  before_filter :load_parameters, :except => [:index, :find_only_param]
  before_filter :load_defect_collection, :load_wish_list, :load_styles
  before_filter :clear_paginate_page_from_session, :only => [:find, :find_only_param, :find_all_thematics, :find_all_authors, :find_all_countries, :find_all_publishers, :find_all_years, :find_all_editions]

  #guardo la ultima url visitada del controller mientras el usuario no tenia session.
  #esto me permite mandarlo a la misma pagina cuando se loguea
  before_filter :last_url_without_session

  def sort_catalog
    @order_type_selected = params[:order_type_selected]

    if session[:filter_params].nil?
      filter_params = OpenStruct.new
    else
      filter_params = session[:filter_params]
    end

    filter_params.catalog_order_type = @order_type_selected
    session[:filter_params] = filter_params

    find_materials_without_trees_filters
    render :partial=>'catalogs/material_list', :layout=>false
  end

  def last_url_without_session
    if current_user.nil?
      session[:last_url_without_session] = request.request_uri
    end
  end


  def auto_complete_descriptor
    finder = params[:descriptor1] unless params[:descriptor1].nil?
    finder = params[:descriptor2] unless params[:descriptor2].nil?
    finder = params[:descriptor3] unless params[:descriptor3].nil?

    if !finder.nil?
      @descriptors= Descriptor.engine_search_by_description finder
    end

    render :layout=>false
  end

  def index_without_clean
    #levanto la bandera de no limpiar los parametros y redirijo al index que hace todo el laburo posta
    session[:catalog_index_without_clean] = true
    redirect_to catalogs_path
  end

  def index
    #si vengo del action index_without_clean significa que no tengo que limpiar los filtros y debo cargar los parametros que hayan
    if session[:catalog_index_without_clean] == true
      load_parameters
    else
      clear_parameters
    end
    #borro la bandera..
    session[:catalog_index_without_clean] = nil

    #se arma el sector de los filtros y se cargan los materiales segun los parametros cargados.
    puts "---------------------------------"
    start = Time.now
    find_materials_with_trees_filters
    load_trees_filters
    puts "demora TOTAL #{Time.now - start} segundos"
    puts "---------------------------------"
    create_find_tags

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @materials }
    end
  end

  def find_only_param

    clear_parameters

    record = if session[:filter_params].nil? then OpenStruct.new else session[:filter_params] end

    record.thematic_id = params[:thematic_id] unless params[:thematic_id].nil?
    record.author_id = params[:author_id] unless params[:author_id].nil?
    record.publisher_country_id = params[:country_id] unless params[:country_id].nil?
    record.publisher_id = params[:publisher_id] unless params[:publisher_id].nil?
    record.edition_year = params[:year] unless params[:year].nil?
    record.edition_number = params[:edition] unless params[:edition].nil?
    
    session[:filter_params] = record

    #levanto la bandera de no limpiar los parametros y redirijo al index que hace todo el laburo posta
    session[:catalog_index_without_clean] = true
    redirect_to catalogs_path
  end

  #busqueda por los filtros (los parametros se cargan en load_parameters)
  def find
    session[:show_filters] = 1

    #levanto la bandera de no limpiar los parametros y redirijo al index que hace todo el laburo posta
    session[:catalog_index_without_clean] = true
    redirect_to catalogs_path
  end

  def find_all_thematics
    record = session[:filter_params]
    record.thematic_id = nil
    session[:filter_params] = record
    find
  end

  def find_all_authors
    record = session[:filter_params]
    record.author_id = nil
    session[:filter_params] = record
    find
  end

  def find_all_countries
    record = session[:filter_params]
    record.publisher_country_id = nil
    session[:filter_params] = record
    find
  end

  def find_all_publishers
    record = session[:filter_params]
    record.publisher_id = nil
    session[:filter_params] = record
    find
  end

  def find_all_years
    record = session[:filter_params]
    record.edition_year = nil
    session[:filter_params] = record
    find
  end

  def find_all_editions
    record = session[:filter_params]
    record.edition_number = nil
    session[:filter_params] = record
    find
  end

  def load_trees_filters
    start = Time.now
    find_tree_authors
    find_tree_countries
    find_tree_editors
    find_tree_years
    find_tree_editions
    find_tree_thematics
    puts "demora catalog.load_trees_filters #{Time.now - start} segundos"
  end

  def find_tree_thematics
    start = Time.now
    record_search_params = session[:filter_params]
    record_search_result =  search_catalog_filter_trees :thematics, params[:page_thematics_filter]
    @material_thematics = record_search_result.filter_tree_thematics
    @material_thematics.map!{|e| [e[0], Thematic.find(e[0]).name_to_local_language, e[1]]}
    @material_thematics_return = if record_search_params.thematic_id.nil? then nil else 1 end
    puts "demora catalog.find_tree_thematics #{Time.now - start} segundos"
  end

  def find_tree_authors
    start = Time.now
    record_search_params = session[:filter_params]
    record_search_result = search_catalog_filter_trees :authors, params[:page_author]
    @material_authors = record_search_result.filter_tree_authors
    @material_authors.map!{|e| [e[0], Author.find(e[0]).full_name, e[1]]}
    @material_authors_return = if record_search_params.author_id.nil? then nil else 1 end
    puts "demora catalog.find_tree_authors #{Time.now - start} segundos"
  end

  def find_tree_countries
    start = Time.now
    record_search_params = session[:filter_params]
    record_search_result = search_catalog_filter_trees :countries, params[:page_ceditions]
    @material_country_editions = record_search_result.filter_tree_countries
    @material_country_editions.map!{|e| [e[0], Country.find(e[0]).name, e[1]]}
    @material_countries_return = if record_search_params.country_id.nil? then nil else 1 end
    puts "demora catalog.find_tree_countries #{Time.now - start} segundos"
  end

  def find_tree_editors
    start = Time.now
    record_search_params = session[:filter_params]
    record_search_result = search_catalog_filter_trees :publishers, params[:page_editors]
    @material_editors = record_search_result.filter_tree_publishers
    @material_editors.map!{|e| [e[0], Publisher.find(e[0]).name, e[1]]}
    @material_publishers_return = if record_search_params.publisher_id.nil? then nil else 1 end
    puts "demora catalog.find_tree_editors #{Time.now - start} segundos"
  end

  def find_tree_years
    start = Time.now
    record_search_params = session[:filter_params]
    record_search_result = search_catalog_filter_trees :years_editions, params[:page_years]
    @material_years = record_search_result.filter_tree_years_editions
    @material_years.map!{|e| [e[0], e[0], e[1]]}
    @material_years_return = if record_search_params.edition_year.nil? then nil else 1 end
    puts "demora catalog.find_tree_years #{Time.now - start} segundos"
  end

  def find_tree_editions
    start = Time.now
    record_search_params = session[:filter_params]
    record_search_result = search_catalog_filter_trees :editions, params[:page_edit]
    @material_editions = record_search_result.filter_tree_editions
    @material_editions.map!{|e| [e[0], e[0], e[1]]}
    @material_editions_return = if record_search_params.edition_number.nil? then nil else 1 end
    puts "demora catalog.find_tree_editions #{Time.now - start} segundos"
  end

  def find_materials_with_trees_filters
    start = Time.now
    record_search_result = Material.search_engine_from_catalog current_user, session[:catalog_paginate_page], session[:filter_params], true
    @materials = record_search_result.materials
    session[:catalog_filters_trees] = record_search_result.filters_trees
    puts "demora catalog.find_materials_without_trees_filters #{Time.now - start} segundos"
  end

  def find_materials_without_trees_filters
    start = Time.now
    record_search_result = Material.search_engine_from_catalog current_user, session[:catalog_paginate_page], session[:filter_params], false
    @materials = record_search_result.materials
    puts "demora catalog.find_materials_without_trees_filters #{Time.now - start} segundos"
  end

  def paginate_materials
    # Se guarda la pagina actual en la session
    # esto nos permite saber en que pagina estaba parado el usuario cuando se invoca al action index_without_clean
    # este valor se limpiar en el action :clear_paginate_page_from_session except => [:show_material_details, index_without_clean, save_wish_list]
    session[:catalog_paginate_page] = params[:page]

    find_materials_without_trees_filters
    render :partial=>'catalogs/paginate_material_list' , :layout=>false
  end

  def paginate_tree_thematics_filter
    find_tree_thematics
    render :partial=>'catalogs/filters/paginate_tree_thematics_filter' , :layout=>false
  end

  def paginate_tree_authors
    find_tree_authors
    render :partial=>'catalogs/filters/paginate_tree_authors' , :layout=>false
  end

  def paginate_tree_countries
    find_tree_countries
    render :partial=>'catalogs/filters/paginate_tree_countries' , :layout=>false
  end

  def paginate_tree_editors
    find_tree_editors
    render :partial=>'catalogs/filters/paginate_tree_editors' , :layout=>false
  end

  def paginate_tree_years
    find_tree_years
    render :partial=>'catalogs/filters/paginate_tree_years' , :layout=>false
  end

  def paginate_tree_editions
    find_tree_editions
    render :partial=>'catalogs/filters/paginate_tree_editions' , :layout=>false
  end

  #cargo los parametros de busqueda
  def load_parameters
    @show_filters =session[:show_filters]

    record = if session[:filter_params].nil? then OpenStruct.new else session[:filter_params] end

    #parametro de busqueda libre
    record.free_text_search = params[:free_text_search] unless params[:free_text_search].nil? || params[:free_text_search].size == 0

    #parametros de los filtros
    record.thematic_id = params[:thematic_id] unless params[:thematic_id].nil?
    record.author_id = params[:author_id] unless params[:author_id].nil?
    record.publisher_id = params[:publisher_id] unless params[:publisher_id].nil?
    record.publisher_country_id = params[:country_id] unless params[:country_id].nil?
    record.edition_year = params[:year] unless params[:year].nil?
    record.edition_number = params[:edition] unless params[:edition].nil?

    #parametros de la busqueda avanzada
    record.title = params[:advance_search_title] unless params[:advance_search_title].nil? || params[:advance_search_title].size == 0
    record.isbn = params[:advance_search_isbn] unless params[:advance_search_isbn].nil? || params[:advance_search_isbn].size == 0
    record.author_full_name = params[:advance_search_author] unless params[:advance_search_author].nil? || params[:advance_search_author].size == 0
    record.publisher_name = params[:advance_search_publisher] unless params[:advance_search_publisher].nil? || params[:advance_search_publisher].size == 0
    record.publisher_country_name = params[:advance_search_country] unless params[:advance_search_country].nil? || params[:advance_search_country].size == 0
    record.edition_year = params[:advance_search_year_search] unless params[:advance_search_year_search].nil? || params[:advance_search_year_search].size == 0
    record.descriptor1 = params[:descriptor1] unless params[:descriptor1].nil? || params[:descriptor1].size == 0
    record.descriptor2 = params[:descriptor2] unless params[:descriptor2].nil? || params[:descriptor2].size == 0
    record.descriptor3 = params[:descriptor3] unless params[:descriptor3].nil? || params[:descriptor3].size == 0
    record.descriptor_connector1 = params[:connector1] unless params[:connector1].nil?
    record.descriptor_connector2 = params[:connector2] unless params[:connector2].nil?

    #temporal que se usa solo para armar el texto de los filtros (sino se confunde con el filtro de año que agrupa)
    record.edition_year_advance_search = params[:advance_search_year_search] unless params[:advance_search_year_search].nil? || params[:advance_search_year_search].size == 0
    record.edition_year_filter = params[:year] unless params[:year].nil?

    session[:filter_params] = record
  end

  def clear_paginate_page_from_session
    session[:catalog_paginate_page] = nil
  end

  def clear_parameters

    session[:catalog_paginate_page] = nil
    session[:show_filters] = 0
    @show_filters = 0

    record = if session[:filter_params].nil? then OpenStruct.new else session[:filter_params] end

    record.title = nil
    record.isbn =  nil
    record.edition_year = nil
    record.edition_year_filter = nil
    record.edition_year_advance_search = nil
    record.edition_number = nil
    record.author_id = nil
    record.author_full_name = nil
    record.publisher_id = nil
    record.publisher_name = nil
    record.publisher_country_id = nil
    record.publisher_country_name = nil
    record.thematic_id = nil
    record.descriptor1 = nil
    record.descriptor2 = nil
    record.descriptor3 = nil
    record.descriptor_connector1 = nil
    record.descriptor_connector2 = nil
    record.free_text_search = nil
    
    session[:filter_params] = record
  end

  def create_find_tags
    record = if session[:filter_params].nil? then OpenStruct.new else session[:filter_params] end

    advance_search_tags = ""
    advance_search_tags += "'ti: #{record.title}' " unless record.title.nil?
    advance_search_tags += ", " if !record.author_full_name.nil? && advance_search_tags != ""
    advance_search_tags += "'au: #{record.author_full_name}' " unless record.author_full_name.nil?
    advance_search_tags += ", " if !record.publisher_country_name.nil? && advance_search_tags != ""
    advance_search_tags += "'co: #{record.publisher_country_name}' " unless record.publisher_country_name.nil?
    advance_search_tags += ", " if !record.publisher_name.nil? && advance_search_tags != ""
    advance_search_tags += "'pu: #{record.publisher_name}' " unless record.publisher_name.nil?
    advance_search_tags += ", " if !record.edition_year_advance_search.nil? && advance_search_tags != ""
    advance_search_tags += "'ye: #{record.edition_year_advance_search}'" unless record.edition_year_advance_search.nil?
    advance_search_tags += ", " if !record.edition_number.nil? && advance_search_tags != ""
    advance_search_tags += "'ed: #{record.edition_number}'" unless record.edition_number.nil?
    advance_search_tags += ", " if !record.isbn.nil? && advance_search_tags != ""
    advance_search_tags += "'is: #{record.isbn}'" unless record.isbn.nil?

    advance_search_tags += ", " if !record.descriptor1.nil? && advance_search_tags != ""
    advance_search_tags += "'de1: #{record.descriptor1}'" unless record.descriptor1.nil? || record.descriptor1.nil?
    advance_search_tags += " #{record.descriptor_connector1} " if !record.descriptor1.nil? && !record.descriptor2.nil?
    advance_search_tags += "'de2: #{record.descriptor2}'" unless record.descriptor2.nil?
    advance_search_tags += " #{record.descriptor_connector2} " if !record.descriptor3.nil? && (!record.descriptor1.nil? || !record.descriptor2.nil?)
    advance_search_tags += "'de3: #{record.descriptor3}'" unless record.descriptor3.nil?

    @filters_data = []

    @filters_data += [:name => 'free_text_search_filter', :data => record.free_text_search] unless record.free_text_search.nil? || record.free_text_search == ""
    @filters_data += [:name => 'advanced_search_filter', :data => advance_search_tags] unless advance_search_tags == ""
    thematic = Thematic.find record.thematic_id unless record.thematic_id.nil?
    @filters_data += [:name => 'thematic_filter', :data => thematic.name_to_local_language] unless thematic.nil?
    author = Author.find record.author_id unless record.author_id.nil?
    @filters_data += [:name => 'author_filter', :data => author.full_name] unless author.nil?
    country = Country.find record.publisher_country_id unless record.publisher_country_id.nil?
    @filters_data += [:name => 'country_filter', :data => country.name] unless country.nil?
    publisher = Publisher.find record.publisher_id unless record.publisher_id.nil?
    @filters_data += [:name => 'publisher_filter', :data => publisher.name] unless publisher.nil?
    @filters_data += [:name => 'year_filter', :data =>record.edition_year_filter] unless record.edition_year_filter.nil?
    @filters_data += [:name => 'edition_filter', :data => record.edition_number] unless record.edition_number.nil?
  end

  def advanced_search_view
  end

  def advanced_search
    clear_parameters
    load_parameters
    session[:show_filters] = 1

    #redirijo al index sin limpiar los filtros
    redirect_to catalogs_index_without_clean_path
  end

  def free_text_search
    clear_parameters
    load_parameters
    session[:show_filters] = 1

    #redirijo al index sin limpiar los filtros
    redirect_to catalogs_index_without_clean_path
  end

  def go_to_filters
    session[:show_filters] = 1
    @show_filters = 1

    #redirijo al index sin limpiar los filtros
    redirect_to catalogs_index_without_clean_path
  end

  #carga el combo de las listas
  def load_wish_list
    if !current_user.nil?
      wish_lists_special = WishList.find :all, :conditions => ["user_id = ? and type_list != ?", current_user.id, WishList::TYPE_SIMPLE], :order => "name"
      wish_lists_simple = WishList.find(:all, :conditions => ["user_id = ? and type_list = ?", current_user.id, WishList::TYPE_SIMPLE], :order => "name")
      @wish_lists = wish_lists_special + wish_lists_simple
    else
      @wish_lists = []
    end
  end

  #cargo los valores por defecto de las colecciones
  def load_defect_collection
    @categories = Category.find(:all, :conditions => "category_id is null")
    @materials = nil
    @order_type_selected = 'catalog_order_types.title'

    record = OpenStruct.new if session[:filter_params].nil?
    record = session[:filter_params] unless session[:filter_params].nil?
    @order_type_selected = record.catalog_order_type
  end

  def save_wish_list
    error = false

    if !params[:wish_list_selected].nil? && params[:wish_list_selected] != "-1"
      wish_list_id = params[:wish_list_selected].to_i
    else
      flash[:error] = t('lbl_select_wish_list')
      error = true
    end

    if !error
      if !params[:material_selected].nil?
        materials_id = []
        if params[:material_selected].is_a?(Array)
          params[:material_selected].each { |material_id_str| materials_id << material_id_str.to_i }
          if materials_id.size == 0
            flash[:error] = t('lbl_must_select_materials')
            error = true
          end
        else
          materials_id << params[:material_selected].to_i
        end
      else
        flash[:error] = t('lbl_must_select_materials')
        error = true
      end
    end

    if !error
      wish_list = WishList.find wish_list_id
      if wish_list.type_list == WishList::TYPE_CART
        #si la lista es el carro de compras
        session[:materials_id_to_add_cart] = materials_id
        redirect_to my_wish_list_define_materials_to_cart_from_catalog_path
      else
        #sino lo trato como una lista comun
        process_with_error = WishListsHelper.add_materials_to_wish_list(wish_list_id, materials_id)
        if process_with_error
          flash[:error] = t('lbl_material_add_wish_list_error')
        else
          flash[:notice] = t('lbl_material_add_wish_list_ok')
        end
      end
    end
    if error || wish_list.type_list != WishList::TYPE_CART
      index_without_clean
    end
  end

  def show_material_details
    @filters = 0
    @show_details = 1
    @material= Material.find params[:id], :include => [:authors, {:publishers => [ {:city => [:state => :country]}]}, :thematic, :descriptors]

    access_denied = false

    # se controla el show_web y el precio
    if !@material.show_web || @material.price.nil? || @material.price == 0
      access_denied = true
    end

    # se controla que el libro no sea cubano si el usuario no esta logueado
    if current_user.nil?
      country_id_cuba = Setting.country_id_cuba

      if !country_id_cuba.nil?
        @material.publishers.each { |publisher|
          if publisher.city.state.country.id == country_id_cuba
            access_denied = true
            break
          end
        }
      end
    end
    if access_denied
      show_page_access_denied
    else
      # seteo a que lista tiene que volver
      session[:special_return_to_controller] = "catalogs"
      session[:special_return_to_code] = nil
      render 'materials/material_info_for_details'
    end
  end

  def load_styles
    @size_font_header = 13
    @size_font_paginate = 11
    @size_font_title_filter = 13
    @td_height_title_filter = 30
    @inner_window = 0
    @outer_window = 0
  end

  def special_return_to
    session[:special_return_to_controller] = nil
    session[:special_return_to_code] = nil
    index_without_clean
  end
end